﻿using Microsoft.AspNetCore.SignalR.Client;
using Newtonsoft.Json;
using NLog.Fluent;
using Simple.BasicNet.Core;
using Simple.BasicNet.Core.Configuration;
using Simple.BasicNet.Core.Handle;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

/*********************************************************
 * 命名空间 App.Extension
 * 接口名称 IDTContext
 * 开发人员：11920
 * 创建时间：2023/4/14 14:40:15
 * 描述说明：
 * 更改历史：
 * 
 * *******************************************************/
namespace App.Extension
{
	public class IDTContext:HandleContext,IContext
	{
		public IDTContext(IConfiguration configution,ILogger logger)
		{

			Device = new DeviceInfo();
			this.logger = logger;
			Dic_commands = new Dictionary<string,Command>();
			this.configution = configution;
		}

		public DeviceInfo Device { get { return device; } set { device = value; } }
		public DeviceStatus DeviceStatus { get { return deviceStatus; } set { deviceStatus = value; } }

		public HubConnection SignalR { get { return signalR; } set { signalR = value; } }
		public Dictionary<string,Command> Dic_commands { get { return dic_command; } set { dic_command = value; } }
		public Guid SendTableConnectionKey { get { return sendTableConnectionKey; } set { sendTableConnectionKey = value; } }

		private DeviceInfo device;
		private DeviceStatus deviceStatus;
		private DateTime time;
		private HubConnection signalR;
		private IConfiguration configution;

		private Dictionary<string, Command> dic_command;

		private ILogger logger;

		private Guid sendTableConnectionKey;

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public string GetDeviceInfo()
		{
		 return JsonConvert.SerializeObject(new
			{
				cmd =CurrentPack.CommandID,
				data = new
				{
					DeviceSn = Device.SN,
					Manufacturer = Device.Manufacture,
					Version = Device.WareVersion,
					ProductType = Device.ProductType,
					ParentDeviceID = Device.ParentDeviceID,
					AuthorizeKey = Device.AuthorizeKey,
					IsRelogin = Device.IsRelogin
				}
			});
		}

		/// <summary>
		/// 
		/// </summary>
		public void RefreshHeartTime()
		{
				time = DateTime.Now;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="second"></param>
		/// <returns></returns>
		public bool CheckHeartIsPast(int second=600)
		{
			if (DateTime.Now<=time.AddSeconds(second))
			{
				return false;
			}
			return true;
		}

		public async Task CreateIignalRConneciont()
		{
			if (string.IsNullOrWhiteSpace(Device.SN))
			{
				return;
			}
			var data  = JsonConvert.SerializeObject(new { cmd = CurrentPack.CommandID,
				data = new { DeviceSn = Device.SN, Manufacturer = Device.Manufacture, 
					Version = Device.WareVersion, ProductType = Device.ProductType,
					ParentDeviceID = Device.ParentDeviceID, 
					AuthorizeKey = Device.AuthorizeKey, IsRelogin = Device.IsRelogin
				} });// GetDeviceInfo();
			if (SignalR != null)
			{
				if (!string.IsNullOrEmpty(Device.SN))
				{
					if (SignalR.State == HubConnectionState.Connected)
					{
						SendSignalR(data);
					}
				}
			}
			else
			{
				if (CurrentPack.CommandID== 16 || CurrentPack.CommandID == 20)
				{
					var ptype = GetPType();
					if (ptype != 64 && ptype != 65)
					{
						return;
					}
					int clientType = ptype == 64 ? 4 : 5;
					var groupName = Device.SN;
					if (clientType == 4)
					{
						groupName = Device.ParentDeviceID; // jobject["data"]["ParentDeviceID"].ToString();
					}
					//bool.Parse(jobject["data"]["IsRelogin"].ToString());
					//var baseConfig = configuration.GetSection("BaseConfig").Get<BaseConfig>();

					var SignalRServer = configution.GetConfiguration<IDTConfiguration>().SignalRServerAddress;// "http://172.16.1.128:9003/signalr/dtm";
						Uri uri = new Uri($"{configution.GetConfiguration<IDTConfiguration>().SignalRServerAddress}?clientType={clientType}&clientName={Device.SN}&groupName={groupName}&relogin={Device.IsRelogin}");
						SignalR = new HubConnectionBuilder().WithUrl(uri)
							   .WithAutomaticReconnect(new RandomRetryPolicy(20, SignalRServer, Device.SN, logger))
							   .Build();
				
					SignalR.On<string, string>("CommandRecive", (sn, message) =>
					{
						string commandId = "";


						//var socket = socketConnectionHandler.GetSocketById(sn);
						logger.Info($"沙盘号{sn}");
						var byteData = GetServerToClientData(message, ref commandId);
						dic_command.Add(commandId,new Command()
						{
							buffer= byteData,
							sendTime=DateTime.Now,
							status=0,
							resendCount=1,
						});
						Send(byteData);
						logger.Info(message);
					});
					SignalR.On<int, int, string>("Connected", (isOnline, clientType, message) =>
					{
						if (isOnline == 1)
						logger.Info(message);
					});
					SignalR.On("DisConnect", async () => {
						await SignalR.StopAsync();
					});
					SignalR.On<string, string>("ReceiveMessage", (user, message) =>
					{
						logger.Info(message);
					});
					SignalR.On<string>("DisConnected", async (msg) =>
					{
						await SignalR.StopAsync();
						logger.Info($"signalr连接失败{msg}");
					});
					SignalR.Closed += error =>
					{
						logger.Warn("SignalR close!");
						return Task.CompletedTask;
					};
					try
					{
						await SignalR.StartAsync();

						if (!string.IsNullOrWhiteSpace(data))
						{
							if (SignalR.State == HubConnectionState.Connected)
							{
								SendSignalR(data);
							}
							else
							{
								logger.Info($"{SignalR.State}");
							}
						}
					}
					catch (Exception ex)
					{
						logger.Info($"signalr连接失败：{ex.Message}");
						await SignalR.StartAsync();
					}
				}
				//else
				//{
				//    socketConnectionHandler.RemoveSocket(deviceSn);
				//}
			}
			return;
		}

	    public  void SendSignalR(string data)
		{
			switch (Device.eProductType)
			{
				case eProductType.SendTable:
					 SignalR.SendAsync("CommandRecive", Device.SN, data).Wait();
					break;
				case eProductType.Table:
					 SignalR.SendAsync("TableCommandRecive", Device.SN, data).Wait();
					break;
				default:
					break;
			}
		}

		public int GetPType()
		{
			int.TryParse(Device.ProductType,out int ptype);
			return ptype;
		}
		public byte[] GetServerToClientData(string data, ref string commandId)
		{
			byte[] dataBuffer = Encoding.UTF8.GetBytes(data);
			byte[] dataLength = BitConverter.GetBytes(dataBuffer.Length);
			commandId = Guid.NewGuid().ToString().Replace("-", "");
			byte[] DownloadDataID = Encoding.UTF8.GetBytes(commandId);

			Array.Reverse(dataLength);
			byte[] buffer = new byte[dataBuffer.Length + 42];
			Array.Copy(Common.Head, 0, buffer, 0, 2);
			buffer[2] = 0x12;
			Array.Copy(dataLength, 0, buffer, 3, 4);
			Array.Copy(dataBuffer, 0, buffer, 7, dataBuffer.Length);
			Array.Copy(DownloadDataID, 0, buffer, 7 + dataBuffer.Length, DownloadDataID.Length);
			buffer[buffer.Length - 3] = (byte)buffer.CalculateChecksum(buffer.Length - 3);
			Array.Copy(Common.Tail, 0, buffer, buffer.Length - 2, 2);
			return buffer;
		}

		public void AddCommand(string cmd,Command command)
		{
			if (!dic_command.ContainsKey(cmd))
			{
				dic_command.Add(cmd,command);
			}
		}
	}
}
